package com.sms.service.impl;

import com.sms.exception.DataFileCorruptedException;
import com.sms.exception.SMSException;
import com.sms.model.Student;
import com.sms.service.StudentService;
import com.sms.util.FileUtil;
import com.sms.util.ValidateUtil;

import java.io.IOException;
import java.util.*;

import static com.sms.constants.SystemConstants.STUDENT_FILE;

public class StudentServiceImpl implements StudentService {
    /**
     * 添加学生信息
     *
     * @param student 学生对象
     * @throws SMSException               当学号已存在或数据无效时抛出
     * @throws DataFileCorruptedException 当数据文件损坏时抛出
     */
    @Override
    public void addStudent(Student student) throws SMSException, DataFileCorruptedException {
        if (student == null) {
            throw new SMSException("学生对象不能为null");
        }

        if (!student.isValid()) {
            throw new SMSException("学生数据无效！");
        }
        try {
            String s_id = student.getId();
            //检查数据文件是否存在，若不存在自动创建
            FileUtil.createFileIfNotExists(STUDENT_FILE);
            //读取存在学生数据
            List<Student> students = FileUtil.loadStudents(STUDENT_FILE);
            //检查学号是否存在
            for (Student s : students) {
                if (s.getId().equals(s_id)) {
                    throw new SMSException("学生学号已存在！");
                }
            }
            //转化类型
            String studentFileString = student.toFileString();
            //存入文件(追加)
            List<String> lines = new ArrayList<>();
            lines.add(studentFileString);
            FileUtil.writeLines(STUDENT_FILE, lines, true);
        } catch (IOException e) {
            throw new DataFileCorruptedException("学生数据文件读写失败: " + e.getMessage());
        }
    }

    /**
     * 删除学生信息
     *
     * @param studentId 学号
     * @return true-删除成功, false-学生不存在
     * @throws DataFileCorruptedException 当数据文件损坏时抛出
     */
    @Override
    public boolean deleteStudent(String studentId) throws DataFileCorruptedException {
        try {
            if (!ValidateUtil.isValidStudentId(studentId)) {
                throw new DataFileCorruptedException("学号格式错误!");
            }
            //检查数据文件是否存在
            if (!FileUtil.fileExists(STUDENT_FILE)) {
                return false;
            }
            //读取存在学生数据
            List<Student> students = FileUtil.loadStudents(STUDENT_FILE);
            //检查学号是否存在
            boolean removed = students.removeIf(s -> s.getId().equals(studentId));
            //保存文件(追加)
            FileUtil.saveStudents(STUDENT_FILE, students);
            return removed;
        } catch (IOException e) {
            throw new DataFileCorruptedException("学生数据文件读写失败: " + e.getMessage());
        }
    }

    /**
     * 根据学号查询学生信息
     *
     * @param studentId 学号
     * @return 学生对象，未找到时返回null
     * @throws DataFileCorruptedException 当数据文件损坏时抛出
     */
    @Override
    public Student getStudent(String studentId) throws DataFileCorruptedException {
        try {
            if (!ValidateUtil.isValidStudentId(studentId)) {
                throw new DataFileCorruptedException("学号格式错误!");
            }
            //检查数据文件是否存在
            if (!FileUtil.fileExists(STUDENT_FILE)) {
                return null;
            }
            //读取存在学生数据
            List<Student> students = FileUtil.loadStudents(STUDENT_FILE);
            //检查学号是否存在
            for (Student student : students) {
                if (student.getId().equals(studentId)) {
                    return student;
                }
            }
            return null;
        } catch (IOException e) {
            throw new DataFileCorruptedException("学生数据文件读写失败: " + e.getMessage());
        }
    }

    /**
     * 获取所有学生列表
     *
     * @return 学生列表（按学号排序）
     * @throws DataFileCorruptedException 当数据文件损坏时抛出
     */
    @Override
    public List<Student> getAllStudents() throws DataFileCorruptedException {
        try {
            //检查数据文件是否存在
            if (!FileUtil.fileExists(STUDENT_FILE)) {
                return Collections.emptyList();
            }
            //读取存在学生数据
            List<Student> students = FileUtil.loadStudents(STUDENT_FILE);
            students.sort(Comparator.comparing(Student::getId)); // 实现按学号排序
            return students;
        } catch (IOException e) {
            throw new DataFileCorruptedException("学生数据文件读写失败: " + e.getMessage());
        }
    }

    /**
     * 更新学生信息
     *
     * @param student 学生对象（包含更新后的数据）
     * @return true-更新成功, false-学生不存在
     * @throws SMSException               当数据无效时抛出
     * @throws DataFileCorruptedException 当数据文件损坏时抛出
     */
    @Override
    public boolean updateStudent(Student student) throws SMSException, DataFileCorruptedException {
        // 参数校验
        if (student == null) {
            throw new SMSException("学生对象不能为null");
        }

        if (!student.isValid()) {
            throw new SMSException("学生数据无效！");
        }

        try {
            // 检查文件是否存在
            if (!FileUtil.fileExists(STUDENT_FILE)) {
                return false;
            }

            // 读取数据
            List<Student> students = FileUtil.loadStudents(STUDENT_FILE);

            // 查找并更新学生
            boolean updated = false;
            for (int i = 0; i < students.size(); i++) {
                if (students.get(i).getId().equals(student.getId())) {
                    students.set(i, student);
                    updated = true;
                    break;
                }
            }

            if (!updated) {
                return false;
            }

            // 保存数据
            FileUtil.saveStudents(STUDENT_FILE, students);

            return true;
        } catch (IOException e) {
            throw new DataFileCorruptedException("学生数据文件操作失败: " + e.getMessage());
        }
    }

    /**
     * 根据姓名搜索学生
     *
     * @param name 姓名（支持模糊匹配）
     * @return 匹配的学生列表
     * @throws DataFileCorruptedException 当数据文件损坏时抛出
     */
    @Override
    public List<Student> searchStudentsByName(String name) throws DataFileCorruptedException {
        // 参数校验
        if (name == null) {
            throw new DataFileCorruptedException("学生名称不能为null");
        }

        if (!ValidateUtil.isValidName(name)) {
            throw new DataFileCorruptedException("学生名称无效！");
        }

        try {
            // 检查文件是否存在
            if (!FileUtil.fileExists(STUDENT_FILE)) {
                throw new DataFileCorruptedException("学生文件无效！");
            }

            // 读取数据
            List<Student> students = FileUtil.loadStudents(STUDENT_FILE);
            List<Student> find_students = new ArrayList<>();
            // 查找并学生名称
            for(Student student : students){
                if(student.getName().equals(name)){
                    find_students.add(student);
                }
            }

            return find_students;
        } catch (IOException e) {
            throw new DataFileCorruptedException("学生数据文件操作失败: " + e.getMessage());
        }
    }

    /**
     * 根据班级查询学生
     *
     * @param className 班级名称
     * @return 该班级的学生列表
     * @throws DataFileCorruptedException 当数据文件损坏时抛出
     */
    @Override
    public List<Student> getStudentsByClass(String className) throws DataFileCorruptedException {
        // 参数校验
        if (className == null) {
            throw new DataFileCorruptedException("学生班级名称不能为null");
        }

        try {
            // 检查文件是否存在
            if (!FileUtil.fileExists(STUDENT_FILE)) {
                throw new DataFileCorruptedException("学生文件无效！");
            }

            // 读取数据
            List<Student> students = FileUtil.loadStudents(STUDENT_FILE);
            List<Student> find_students = new ArrayList<>();
            // 查找并学生名称
            for(Student student : students){
                if(student.getClassName().equals(className)){
                    find_students.add(student);
                }
            }

            return find_students;
        } catch (IOException e) {
            throw new DataFileCorruptedException("学生数据文件操作失败: " + e.getMessage());
        }
    }


    /**
     * 批量添加学生
     *
     * @param students 学生列表
     * @return 成功添加的学生数量
     * @throws SMSException               当学号重复或数据无效时抛出
     * @throws DataFileCorruptedException 当数据文件损坏时抛出
     */
    @Override
    public int batchAddStudents(List<Student> students) throws SMSException, DataFileCorruptedException {
        if (students == null || students.isEmpty()) {
            throw new SMSException("学生列表不能为空");
        }

        try {
            // 验证所有学生数据
            for (Student s : students) {
                if (!s.isValid()) {
                    throw new SMSException("无效学生数据: " + s.getId());
                }
            }

            // 检查重复学号
            Set<String> ids = new HashSet<>();
            for (Student s : students) {
                if (!ids.add(s.getId())) {
                    throw new SMSException("存在重复学号: " + s.getId());
                }
            }

            // 读取现有数据
            List<Student> existing = FileUtil.fileExists(STUDENT_FILE) ?
                    FileUtil.loadStudents(STUDENT_FILE) : new ArrayList<>();

            // 检查与现有数据的学号冲突
            for (Student s : students) {
                if (existing.stream().anyMatch(e -> e.getId().equals(s.getId()))) {
                    throw new SMSException("学号已存在: " + s.getId());
                }
            }

            // 合并数据
            existing.addAll(students);
            FileUtil.saveStudents(STUDENT_FILE, existing);

            return students.size(); // 返回实际添加数量
        } catch (IOException e) {
            throw new DataFileCorruptedException("学生数据文件读写失败: " + e.getMessage());
        }
    }

    /**
     * 获取学生总数
     *
     * @return 学生数量
     * @throws DataFileCorruptedException 当数据文件损坏时抛出
     */
    @Override
    public int getStudentCount() throws DataFileCorruptedException {
        try {
            // 检查文件是否存在
            if (!FileUtil.fileExists(STUDENT_FILE)) {
                return 0;
            }

            // 读取数据
            List<Student> students = FileUtil.loadStudents(STUDENT_FILE);

            // 返回总数
            return students.size();
        } catch (IOException e) {
            throw new DataFileCorruptedException("学生数据文件操作失败: " + e.getMessage());
        }
    }
}
